import { fromEvent, Observable } from "rxjs";
import { tap, map, mergeMap, mergeAll } from "rxjs/operators";
import { getLogger, randomInterval } from "../utils";

interface Employee {
    employeeName: string;
}
interface Product {
    soldBy: Employee;
    productName: string;
}

function createBtn(name: string) {
    const btn = document.createElement("button");
    btn.innerText = name;
    document.body.appendChild(btn);
    btn.style.margin = "20px";
    return btn;
}
const hireBtn = createBtn("hire a new employee");

const log0 = getLogger("Purpose");
log0("An example demonstrating a company hiring sales employees to sell products");

const logEmployee = getLogger("employee");
const logProduct = getLogger("logProducts");


const hireEvent$ = fromEvent(hireBtn, "click").pipe(map((e, idx) => ({
    employeeName: `employee-${idx + 1}`
} as Employee)));

function startSellingProducts(e: Employee): Observable<Product> {
    return randomInterval().pipe(
        map(i => {
            const p: Product = {
                soldBy: e,
                productName: `product-${i}`
            };
            return p;
        })
    )
}

// merge, map, mergeMap?
// below shows equivalent code, which is sort of like the equivalence of:
// [1, 2, 3].map(i=>[i, i*2]).concatAll() vs 

//map -> mergeAll === mergeMap
//map -> switchAll === switchMap

if (false) {
    hireEvent$
        .pipe(
            tap(e => logEmployee(`hired ${e.employeeName}`)), //Observable<Employee>
            map(startSellingProducts), //Observable<Observable<Product>>, a higher order observable
            mergeAll() //Observable<Product>
        )
        .subscribe(e => logProduct(`${e.soldBy.employeeName} sold ${e.productName}`));
} else {
    hireEvent$
        .pipe(
            tap(e => logEmployee(`hired ${e.employeeName}`)), //Observable<Employee>
            mergeMap(startSellingProducts) //Observable<Product>
        )
        .subscribe(e => logProduct(`${e.soldBy.employeeName} sold ${e.productName}`));
}